package server.core.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import server.core.base.Airplane;
import server.core.base.EntityBase;
import server.core.dao.DaoFactory.daoType;

public enum DataBaseDAO implements Dao {
	ORCL("java:comp/env/jdbc/ORCL");
	private final String dbName;
	private DataBaseDAO(String string) {
		dbName=string;
	}
	
	private Connection getConnection() throws SQLException{
		try {
			Context jdbc = new InitialContext();
			DataSource dataSource=(DataSource) jdbc.lookup(this.dbName);
			return dataSource.getConnection();
		} catch (NamingException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public long saveObject(EntityBase entity) {
		Connection con=null;
		PreparedStatement ps=null;
		try {
			con=getConnection();
			ps=con.prepareStatement("insert into Entity(id,name) values(?,?)");
			ps.setLong(1, entity.getId());
			ps.setString(2, entity.getClass().getName());
			if(ps.executeUpdate()!=1)
				throw new SQLException("Failed to save Entity to "+dbName);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(ps!=null)ps.close();
				if(con!=null)con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
		return entity.getId();
	}

	@Override
	public boolean deleteObject(Class<? extends EntityBase> entityClass, long id) {
		Connection con=null;
		PreparedStatement ps=null;
		try {
			con=getConnection();
			ps=con.prepareStatement("delete from Entity where id=?");
			ps.setLong(1, id);
			if(ps.executeUpdate()!=1)
				throw new SQLException("Failed to delete Entity from "+dbName);
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				if(ps!=null)ps.close();
				if(con!=null)con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}

	@Override
	public EntityBase getObject(Class<? extends EntityBase> entityClass, long id) {
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet res=null;
		String name=null;
		try {
			con=getConnection();
			ps=con.prepareStatement("select name from Entity where id=?");
			ps.setLong(1, id);
			res=ps.executeQuery();
			if(res.next()){
				name=res.getString("name");
				return new Airplane(name, 0);
			}else{
				throw new SQLException("Failed to get Entity from "+dbName);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				if(res!=null)res.close();
				if(ps!=null)ps.close();
				if(con!=null)con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}

	@Override
	public daoType getDaoType() {
		return daoType.DATABASE;
	}

	@Override
	public HashMap<Long, ? extends EntityBase> getEntityMap(
			Class<? extends EntityBase> entityObject) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean setEntityMap(Class<? extends EntityBase> entityClass,
			HashMap<Long, ? extends EntityBase> hashmap1) {
		// TODO Auto-generated method stub
		return false;
	}
	
	public Collection findByName(String name){
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet res=null;
		Collection col=new ArrayList();
		try {
			con=getConnection();
			ps=con.prepareStatement("select id from Entity where name=?");
			ps.setString(1, name);
			res=ps.executeQuery();
			while(res.next())
				col.add(new Object());
			if( ! col.isEmpty())
				return col;
			else
				throw new SQLException("Failed to get Entity from "+dbName);
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				if(res!=null)res.close();
				if(ps!=null)ps.close();
				if(con!=null)con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}
	
	public long[] insertEntities(EntityBase... entities){
		Connection con=null;
		PreparedStatement ps=null;
		String sql="insert into Entity(id,name) values(?,?)";
		final int batchSize=1000;
		int count=0;
		long[] ls=new long[entities.length];
		try {
			con=getConnection();
			ps=con.prepareStatement(sql);
			for(int i=0;i<entities.length;i++){
				EntityBase entity=entities[i];
				ps.setLong(1, entity.getId());
				ps.setString(2, entity.getClass().getName());
				ps.addBatch();
				if(++count % batchSize ==0)
					ps.executeBatch();
				ls[i]=entity.getId();
			}
			ps.executeBatch();
//				throw new SQLException("Failed to save Entity to "+dbName);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(ps!=null)ps.close();
				if(con!=null)con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
		return ls;
	}

}
